package hello.app;

import hello.app.component.HistoryAdapter;
import hello.app.component.HistoryItem;
import hello.app.dialog.ProgressDialogEx;
import hello.app.dialog.SelectHistoryBuilder;
import hello.app.dialog.SelectHistorySubBuilder;
import hello.app.model.CommentModel;
import hello.app.model.HelloApi;
import hello.app.model.HelloContactModel;
import hello.app.model.HelloSetting;
import hello.app.model.ModelManager;
import hello.app.model.HelloSetting.DataType;
import hello.app.model.data.CallHistory;
import hello.app.model.data.Comment;
import hello.app.model.data.HelloContact;
import hello.app.model.data.MyContact;
import hello.app.model.data.User;
import hello.app.util.AdteAsyncTask;
import hello.app.util.AdteAsyncTask.BackgroundRunner;
import hello.app.util.AdteAsyncTask.FinishRunner;
import hello.app.util.Debug;
import hello.app.util.ErrorDialogBuilder;
import hello.app.util.ThreadUtil;
import hello.app.util.ThreadUtil.Runner;
import hello.app.util.Util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.StrictMode;
import android.provider.CallLog;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class HistoryActivity extends Activity implements android.view.View.OnClickListener, OnItemClickListener{
	private static final int DIALOG_EMPTY_HISTORY = 1;
	private static final int HELLO_API_ERROR = 2;
	private static final int DIALOG_RECCOMEND = 3;
	private static final int DIALOG_WARNING = 4;
	private static final int DIALOG_STOP = 5;

	private static final int MENU_ID_UPDATE = (Menu.FIRST + 1);
	private static final int MENU_ID_ALL = (Menu.FIRST + 2);
	private static final int MENU_ID_SETTING = (Menu.FIRST + 3);
	private static final int MENU_ID_INCOMING = (Menu.FIRST + 4);
	private static final int MENU_ID_OUTGOING = (Menu.FIRST + 5);
	private static final int MENU_ID_MISSED = (Menu.FIRST + 6);

	private static final int ALL_TYPE = 0;
	ListView mListView;
	ModelManager mManager;
	HelloSetting mSetting;
	CallHistory[] mHistories = null;
	HashMap<String,HelloContact> mHelloContacts;
	private boolean mUseGradeDownView = false;

	class UpdateBtnOnClickListener implements View.OnClickListener{
		public void onClick(View v) {
			updateListView();
		}
	}

	class SettingBtnOnClickListener implements View.OnClickListener{
		public void onClick(View v) {
			if(mSetting.isSuperUser())
        		SettingActivity.start(HistoryActivity.this);
        	else
        		SettingPlusActivity.start(HistoryActivity.this);
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//Debug.disable();
		StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
		setContentView(R.layout.history);
		mManager = ModelManager.getInstatce(this);
		mSetting = mManager.getHelloSetting();
		HelloApi api = mManager.getHelloApi();

		try {
			if(mSetting.getUserId() == HelloSetting.DEFAULT_USER_ID){
				//初期起動
				User loginUser = api.addUser();
				mSetting.write(DataType.SUPER_USER, loginUser.isSuperUser());
				mSetting.write(DataType.USER_ID, loginUser.getId());
			}else if(mSetting.getUserId() != HelloSetting.DEFAULT_USER_ID && !mSetting.isSuperUser()){
				//スーパーユーザーじゃない場合、毎回確認しにいく
				(new ThreadUtil(new Runner() {
					public void exec(Object... args) {
						try {
							User loginUser = mManager.getHelloApi().getUser();
							mSetting.write(DataType.SUPER_USER, loginUser.isSuperUser());
							Debug.log("device_id : " + loginUser.getDeviceId());
						} catch (Exception e) {

						}

					}
				})).start();
				/*
				(new Thread(new Runnable() {
					public void run() {
						try {
							User loginUser = mManager.getHelloApi().getUser();
							mSetting.write(DataType.SUPER_USER, loginUser.isSuperUser());
						} catch (Exception e) {

						}
					}
				})).start();*/
			}

		} catch (IOException ioe) {
			showErrorDlg(getString(R.string.error_network));
			this.finishActivity(-1);
		} catch (Exception e) {
			showErrorDlg(getString(R.string.error_unknown));
			this.finishActivity(-1);
		}finally{
			Debug.log("user_id : " + Integer.toString(mSetting.getUserId()));
			Debug.log("counter : " + Integer.toString(mSetting.getHistoryCounter()));
			Debug.log("super_user : " + mSetting.isSuperUser());
			Debug.log("service_enabled : " + mSetting.isServiceEnabled());
			mHelloContacts = new HashMap<String,HelloContact>();
			mListView = (ListView)findViewById(R.id.hisListView);
			ImageButton updateBtn = (ImageButton)findViewById(R.id.imageButtonUpdate);
			ImageButton settingBtn = (ImageButton)findViewById(R.id.imageButtonSetting);
			updateBtn.setOnClickListener(new UpdateBtnOnClickListener());
			settingBtn.setOnClickListener(new SettingBtnOnClickListener());
			//通知を消す
			NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
			nm.cancelAll();

			// サービスが有効になっていたらスタート
			if (mSetting.isServiceEnabled()) {
				//stopService(new Intent(this, PhoneService.class));
				Debug.log("start phone service");
				stopService(new Intent(this, PhoneService.class));
				startService(new Intent(this, PhoneService.class));
			}
			//限界の回数を超えたら使えなくする
			if(!mSetting.isSuperUser() && mSetting.getHistoryCounter() >= HelloSetting.HISTORY_COUNT_STOP){
				//addUpgradeDetailView();
				addGradeDownlView();
			}
		}
	}

	private void showErrorDlg(String msg){
		ErrorDialogBuilder builder = new ErrorDialogBuilder(this, Application.TITLE, msg);
		builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				HistoryActivity.this.finish();
			}
		});
		builder.create().show();
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_RECCOMEND:
			return createDialog(Application.TITLE, "このアプリは☆5ですか？", new OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					Uri uri;
					Intent intent = new Intent(Intent.ACTION_VIEW);
					uri = Uri.parse("market://details?id=hello.app");

					intent.setData(uri);
					try{
						startActivity(intent);
					}catch (Exception e) {
						intent.setData(Uri.parse("http://play.google.com/store/apps/details?id=hello.app"));
						startActivity(intent);
					}
				}
			},null);
		case DIALOG_WARNING:
			return createDialog(Application.TITLE, "試用期間の期限が近づいています。アップグレードを行えば、引き続き履歴をご利用になれます。");
		case DIALOG_STOP:
			return createDialog(Application.TITLE, "試用期間が過ぎました。アップグレードを行えば、引き続き履歴機能をご利用になれます。");
		case DIALOG_EMPTY_HISTORY:
			ErrorDialogBuilder builder = new ErrorDialogBuilder(this, Application.TITLE, "履歴がありません");
			builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					dialog.cancel();
				}
			});
			return builder.create();
		case HELLO_API_ERROR:
			builder = new ErrorDialogBuilder(this, Application.TITLE, getString(R.string.error_network));
			return builder.create();
		default:
			return null;
		}
	}
	protected Dialog createDialog(String title, String message, OnClickListener onOKlistener, OnClickListener onCancellistener) {

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(title).setIcon(android.R.drawable.stat_sys_warning)
				.setMessage(message).setCancelable(false)
				.setPositiveButton(android.R.string.ok, onOKlistener)
				.setNegativeButton(android.R.string.cancel, onCancellistener);
		return builder.create();
	}

	protected Dialog createDialog(String title, String message) {

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(title).setIcon(android.R.drawable.stat_sys_warning)
				.setMessage(message).setCancelable(false)
				.setPositiveButton(android.R.string.ok, null);
		return builder.create();
	}

	private void addGradeDownlView(){
		mUseGradeDownView = true;
		View view = getLayoutInflater().inflate(R.layout.upgrade_detail, null);
		addContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT));
		Button upgradeBtn = (Button)findViewById(R.id.upgradeBtn);
		upgradeBtn.setOnClickListener(this);
	}
	/*
	private void addUpgradeDetailView(){
		mUseUpgradeView = true;
		View view = getLayoutInflater().inflate(R.layout.upgrade_detail, null);
		addContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT));
		Button upgradeBtn = (Button)findViewById(R.id.upgradeBtn);
		upgradeBtn.setOnClickListener(this);
	}*/

	@Override
	protected void onStart() {
		//Log.d(Debug.TAG, "OnStart HistoryActivity");
		super.onStart();
		initListView();
		HelloSetting setting = mManager.getHelloSetting();
		if(setting.getHistoryCounter() == HelloSetting.DEFAULT_HISTORY_COUNT || setting.isUpdatedApplication(Application.VERSION)){
			updateListView();
			setting.write(DataType.APP_VERSION, Application.VERSION);
			setting.write(DataType.GOOGLE, true);
		}
		if(!setting.isSuperUser()){
			//スーパーユーザーじゃない場合カウントする
			switch(setting.getHistoryCounter()){
			case HelloSetting.HISTORY_COUNT_RECCOMEND:
				showDialog(DIALOG_RECCOMEND);
				break;
			case HelloSetting.HISTORY_COUNT_WARNING:
				showDialog(DIALOG_WARNING);
				break;
			case HelloSetting.HISTORY_COUNT_STOP:
				showDialog(DIALOG_STOP);
				addGradeDownlView();
				initListView(ALL_TYPE);
				//addUpgradeDetailView();
				break;
			}
		}else{
			if(mUseGradeDownView){
				showErrorDlg("アップグレードしましたので、再起動してください");
			}
		}
		setting.addHistoryCounter();
		Debug.log("counter : " + Integer.toString(mSetting.getHistoryCounter()));
	}

	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // メニューアイテムを追加します
        menu.add(Menu.NONE, MENU_ID_UPDATE, Menu.NONE, getString(R.string.history_menu_update));
        menu.add(Menu.NONE, MENU_ID_ALL, Menu.NONE, getString(R.string.history_menu_all));
        menu.add(Menu.NONE, MENU_ID_SETTING, Menu.NONE, getString(R.string.history_menu_setting));
        menu.add(Menu.NONE, MENU_ID_INCOMING, Menu.NONE, getString(R.string.history_menu_incoming));
        menu.add(Menu.NONE, MENU_ID_OUTGOING, Menu.NONE, getString(R.string.history_menu_outgoing));
        menu.add(Menu.NONE, MENU_ID_MISSED, Menu.NONE, getString(R.string.history_menu_missed));
        return super.onCreateOptionsMenu(menu);
    }

	/**
	 * メニューを押したときの処理
	 */
	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        boolean ret = true;
        switch (item.getItemId()) {
        default:
            ret = super.onOptionsItemSelected(item);
            break;
        case MENU_ID_ALL:
        	initListView(ALL_TYPE);
        	break;
        case MENU_ID_SETTING:
        	if(mSetting.isSuperUser())
        		SettingActivity.start(this);
        	else
        		SettingPlusActivity.start(this);
        	break;
        case MENU_ID_INCOMING:
        	initListView(HistoryItem.INCOMING);
        	break;
        case MENU_ID_OUTGOING:
        	initListView(HistoryItem.OUTGOING);
        	break;
        case MENU_ID_MISSED:
        	initListView(HistoryItem.MISSED);
        	break;
        case MENU_ID_UPDATE:
        	updateListView();
            ret = true;
            break;
        }
        return ret;
    }

	/**
	 * リストをクリックした時の動作
	 */
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		HelloContact contact = mHelloContacts.get(mHistories[position].getCachedNumber());
		if(contact != null){
			AlertDialog.Builder builder;
			builder = new SelectHistoryBuilder(HistoryActivity.this,contact, mHistories[position]);
			builder.create().show();
		}
	}

	/**
	 * アップグレードボタンを押した時の動作
	 */
	public void onClick(View v) {
		if(!mSetting.isSuperUser()){
			SettingPlusActivity.startWithUpgrade(this);
		}
	}

	/**
	 * リストの更新
	 */
    private void updateListView(){
    	ProgressDialogEx dlg = new ProgressDialogEx(this, "コンタクトを取得中です。しばらくお待ちください");
		ArrayList<String> numbers = new ArrayList<String>();
    	for(HelloContact c : mHelloContacts.values()){
    		if(c != null){
    			numbers.add(c.getPhone());
    		}
    	}
		AdteAsyncTask task = new AdteAsyncTask(new BackgroundRunner() {
			public Object exec(Object... args) {
				@SuppressWarnings("unchecked")
				ArrayList<String> numbers = (ArrayList<String>) args[0];
				HelloApi api = mManager.getHelloApi();
				boolean ret = false;
				try {
					HelloContact[] contacts = api.getContacts(numbers.toArray(new String[numbers.size()]));
					HelloContactModel contactModel = mManager.getHelloContactModel();
					CommentModel commentModel = mManager.getCommentModel();
					for (HelloContact data : contacts) {
						HelloContact list = mHelloContacts.get(data.getPhone());
						if(list != null){
							if (Util.isSet(list.getName())) {
								data.setName(list.getName());
							}
							contactModel.save(data);
							for(Comment cmt : data.getComments()){
								commentModel.save(cmt);
							}
						}
					}
					ret = true;
				} catch (Exception e) {
					Debug.error(e.getMessage());
					ret = false;
				}
				return ret;
			}
		}, new FinishRunner() {
			public void onFinish(Object success) {
				initListView();
				if ((Boolean)success) {
					Toast.makeText(HistoryActivity.this, "コンタクトを更新しました",
							Toast.LENGTH_LONG).show();
				} else {
					Toast.makeText(HistoryActivity.this,
							"コンタクトを更新できませんでした。ネットワークに繋がっているか確認してください",
							Toast.LENGTH_LONG).show();
				}
			}
		}, (ProgressDialog) dlg, 10);

		// 非同期(スレッド)処理の実行
		task.execute(numbers);
    }

    /**
     * リストの初期化
     * @param filter
     * HistoryItem.INCOMING<br>
     * HistoryItem.OUTGOING<br>
     * HistoryItem.MISSED<br>
     * ALL_TYPEのいずれか<br>
     */
	private void initListView(int filter){
		HistoryAdapter adapter = new HistoryAdapter(this, R.layout.history_row, mUseGradeDownView ? createItemsSub(filter) : createItems(filter));

		if(adapter.getCount() > 0){
			mListView.setAdapter(adapter);
			mListView.setOnItemClickListener(this);
		}else{
			showDialog(DIALOG_EMPTY_HISTORY);
			if(filter != ALL_TYPE){
				initListView(ALL_TYPE);
			}
			return;
		}
		mListView.invalidateViews();
	}
	public void deleteItem(HistoryItem history){
		HistoryAdapter adapter = (HistoryAdapter)mListView.getAdapter();
		adapter.remove(history);
	}

	public void initListView(){
		initListView(ALL_TYPE);
	}

	private HelloContact getHelloContact(HelloContactModel model, CallHistory history){
		HelloContact c = model.findByNumber(history.getCachedNumber());
		if(c == null){
			String name = Util.isSet(history.getCachedName()) ? history.getCachedName() : "";
			c = new HelloContact(0L, name, history.getCachedNumber(), 0, 0, 0, "", "");
		}
		return c;
	}

	private void initMyContacts(HashMap<String,MyContact> contacts){
		contacts.clear();
		MyContact[] temp = mManager.getMyContactModel().findAll();
		if(temp != null){
			for(MyContact c : temp){
				contacts.put(c.getNumber(), c);
			}
		}
	}

	/**
	 * 試用期間が切れた時にはこっち
	 * @param filter
	 * @return
	 */
	private ArrayList<HistoryItem> createItemsSub(int filter){
		String hiddenString = "*******";
		String miniHiddenString = "*";
		HelloContactModel contactModel = mManager.getHelloContactModel();
		CallHistory[] histories = mManager.getCallHistoryModel().find(
				new String[] { CallLog.Calls.CACHED_NAME, CallLog.Calls.NUMBER,
						CallLog.Calls.DATE, CallLog.Calls.TYPE, CallLog.Calls._ID }, null,
				CallLog.Calls.DEFAULT_SORT_ORDER + " limit " + Integer.valueOf(mSetting.getHistoryDisplayCount()));
		LinkedList<CallHistory> list = new LinkedList<CallHistory>();
		mHelloContacts.clear();

		//自分の連絡先にいる場合はそっちを優先する
		HashMap<String,MyContact> myContacts = new HashMap<String,MyContact>();
		initMyContacts(myContacts);

		ArrayList<HistoryItem> items = new ArrayList<HistoryItem>();
		if(histories != null && histories.length != 0){
			for(int i = 0; i < histories.length; i++){
				//0だったらフィルターなし
				if(filter == ALL_TYPE || filter == histories[i].getType()){
					String number = histories[i].getCachedNumber();
					String name = histories[i].getCachedName();
					if(mHelloContacts.containsKey(number) == false){
						HelloContact c = getHelloContact(contactModel, histories[i]);
						mHelloContacts.put(number, c);
					}
					HelloContact e = mHelloContacts.get(number);
					String eval = String.format("%s:%s %s:%s ", getString(R.string.good), miniHiddenString, getString(R.string.bad), miniHiddenString);
					name = hiddenString;
					HashMap<String, String> others = new HashMap<String, String>();
					if(Util.isSet(e.getType())){
						others.put("業種: ", hiddenString);
					}
					if(Util.isSet(e.getAddress())){
						others.put("住所: ", hiddenString);
					}

					HistoryItem item = new HistoryItem(name, e.getPhone(), eval, histories[i].getDate(), others, histories[i].getType(),Util.isMobile(e.getPhone()));
					items.add(item);
					list.add(histories[i]);
				}
			}
		}
		mHistories = list.toArray(new CallHistory[list.size()]);
		return items;
	}

	private ArrayList<HistoryItem> createItems(int filter){
		HelloContactModel evModel = mManager.getHelloContactModel();
		CommentModel cmtModel = mManager.getCommentModel();
		CallHistory[] histories = mManager.getCallHistoryModel().find(
				new String[] { CallLog.Calls.CACHED_NAME, CallLog.Calls.NUMBER,
						CallLog.Calls.DATE, CallLog.Calls.TYPE, CallLog.Calls._ID }, null,
				CallLog.Calls.DEFAULT_SORT_ORDER + " limit " + Integer.valueOf(mSetting.getHistoryDisplayCount()));
		LinkedList<CallHistory> list = new LinkedList<CallHistory>();
		//mHelloContacts.clear();

		//自分の連絡先にいる場合はそっちを優先する
		HashMap<String,MyContact> myContacts = new HashMap<String,MyContact>();
		HashMap<Integer,Comment[]> comments = new HashMap<Integer, Comment[]>();
		initMyContacts(myContacts);

		ArrayList<HistoryItem> items = new ArrayList<HistoryItem>();
		if(histories != null && histories.length != 0){
			for(int i = 0; i < histories.length; i++){
				//0だったらフィルターなし
				if(filter == ALL_TYPE || filter == histories[i].getType()){
					String number = histories[i].getCachedNumber();
					String name = histories[i].getCachedName();
					if(mHelloContacts.containsKey(number) == false){
						mHelloContacts.put(number,getHelloContact(evModel, histories[i]));
					}
					HelloContact contact = mHelloContacts.get(number);
					String eval = String.format("%s:%d %s:%d ", getString(R.string.good), contact.getGood(), getString(R.string.bad), contact.getBad());
					if(!Util.isSet(name)){
						if(myContacts.containsKey(number))
							name = myContacts.get(number).getName();
						else
							name = Util.isSet(contact.getName()) ? contact.getName() : Util.isMobile(contact.getPhone()) ?  "携帯" : "登録名なし";
					}
					HashMap<String, String> others = new HashMap<String, String>();
					if(Util.isSet(contact.getType())){
						others.put("業種: ", contact.getType());
					}
					if(Util.isSet(contact.getAddress())){
						others.put("住所: ", contact.getAddress());
					}
					Comment[] cmts;
					if(comments.containsKey((int)contact.getId()) == false){
						cmts = cmtModel.findByContactId((int)contact.getId());
						comments.put((int)contact.getId(), cmts);
					}else{
						cmts = comments.get((int)contact.getId());
					}
					int cmtCount = Util.isSet(cmts) ? cmts.length : 0;
					if(cmtCount > 0){
						others.put("コメント数: ", String.valueOf(cmtCount));
					}
					HistoryItem item = new HistoryItem(name, contact.getPhone(), eval, histories[i].getDate(), others, histories[i].getType(),Util.isMobile(contact.getPhone()));
					items.add(item);
					list.add(histories[i]);
				}
			}
		}
		mHistories = list.toArray(new CallHistory[list.size()]);
		return items;
	}
}
